<!--
 * @Descripttion: 
 * @version: 
 * @Author: wtzhang
 * @Date: 2021-06-03 14:09:01
 * @LastEditors: wtzhang
 * @LastEditTime: 2021-06-03 14:57:09
-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    // 最基础的类
    function Person() {
      this.name = 'jack';
      this.age = 20;
      this.run = function(){
        console.log(this.name + '在运动');
      }
    }
    // 调用的话，都得实例new
    let p = new Person() 
    console.log(p.name); // jack
    console.log(p.run()); // jack在运动
    Person.prototype.sex = "男"
    Person.prototype.work = function(){
      console.log(this.name + '在工作');
    }
    console.log(p.sex);
    console.log(p.work());
    
    // 第一类：对象冒充继承
    // User类继承 Person类 原型链+对象冒充的组合继承模式
    function User(){
      Person.call(this) //对象冒充实现继承
    }
    let u = new User()
    console.log('User对象冒充继承的Person类：', u.name); // jack
    // console.log('User对象冒充继承的Person类：', u.work()); // error:u.work is not a function, 浅拷贝，原型链追加的无法得到
    // > 总结：对象冒充可以继承构造函数里面的属性和方法，但是无法继承原型链上的属性和方法。

    // 第二类：原型链继承
    function User1(){}
    User1.prototype = new Person()
    let u1 = new User1()
    console.log('原型链继承的person类', u1.run()); // jack在运动
    console.log('原型链继承的person类', u1.work()); // jack在工作
    // > 总结：原型链继承方法，可以同时继承构造函数内，以及person类原型链的书属性和方法。
    console.log('+++++++++++++++++++++++++++++++++++++++++++++');
    // 原型链继承遇到的问题：
    function Person2(name, age){
      this.name = name;
      this.age = age;
      this.run = function(){
        console.log(this.name + '在运动')
      }
    }
    Person2.prototype.work = function(){
      console.log(this.name + '在工作');
    }
    function User2(){}
    User2.prototype = new Person2()
    let u2 = new User2('rose', 20)
    console.log(u2.run()); //undefined在运动
    // > 可见：实例化子类的时候无法给父类传参
console.log('++++++++++++++++++++++++++++++++++++++');
    // 第三种：原型链 + 构造函数的组合继承模式
    function Person3(name, age){
      this.name = name;
      this.age = age;
      this.run = function(){
        console.log(this.name + '在运动')
      }
    }
    Person3.prototype.work = function(){
      console.log(this.name + '在工作');
    }
    function User3(name, age){
      Person3.call(this, name, age) // 对象冒充继承  实例化子类可以给父类传参
    }
    User3.prototype = new Person3()
    let u3 = new User3('rose', 20)
    console.log(u3.run()); // rose在运动
    // > 如此便可可以完美继承，也可以实例化子类可以给父类传参

    console.log('+++++++++++++++++++最后+++++++++++++++++++++++');
    // 第四种：原型链 + 构造函数的组合继承模式
    function Person4(name, age){
      this.name = name;
      this.age = age;
      this.run = function(){
        console.log(this.name + '在运动')
      }
    }
    Person4.prototype.work = function(){
      console.log(this.name + '在工作');
    }
    function User4(name, age){
      Person4.call(this, name, age) // 对象冒充继承  实例化子类可以给父类传参
    }
    // User4.prototype = new Person4() 
    // 本身对象冒充已经将 Person3类的属性方法已经继承，所以这里直接可以继承原型链
    User4.prototype = Person4.prototype
    let u4 = new User4('rose', 20)
    console.log(u4.run()); // rose在运动
    // > 如此便可可以完美继承，也可以实例化子类可以给父类传参
  </script>
</body>
</html>